#include "gofgame/jumpdown/util/HitPoint.h"
#include "gofgame/common/ArgumentException.h"
using namespace gofgame::common;

using namespace gofgame::jumpdown::util;

/* static */ HitPoint *HitPoint::create() {
	HitPoint *retval = new HitPoint();
	retval->init();
	retval->autorelease();
	return retval;
}

/* static */ HitPoint *HitPoint::create(float width, float height, int maxValue) {
	HitPoint *retval = HitPoint::create();
	retval->setMaxValue(maxValue);
	retval->setValue(maxValue);
	retval->setContentSize(CCSize(width, height));
	return retval;
}

HitPoint::HitPoint() {
	this->value = 100;
	this->maxValue = 100;

	ccColor4F color;

	color.r = 0.0F;
	color.g = 0.0F;
	color.b = 0.0F;
	color.a = 0.6F;
	this->backgroundColor = color;

	color.r = 1.0F;
	color.g = 1.0F;
	color.b = 1.0F;
	color.a = 0.6F;
	this->borderColor = color;

	color.r = 1.0F;
	color.g = 1.0F;
	color.b = 1.0F;
	color.a = 0.6F;
	this->borderColor = color;

	color.r = 0.0F;
	color.g = 1.0F;
	color.b = 0.0F;
	color.a = 0.6F;
	this->fullColor = color;

	color.r = 1.0F;
	color.g = 1.0F;
	color.b = 0.0F;
	color.a = 0.6F;
	this->halfColor = color;

	color.r = 1.0F;
	color.g = 0.0F;
	color.b = 0.0F;
	color.a = 0.6F;
	this->emptyColor = color;
}

bool HitPoint::init() {
	//Very important!!!
	this->setShaderProgram(CCShaderCache::sharedShaderCache()->programForKey(kCCShader_PositionColor));
	this->setAnchorPoint(CCPoint(0.5F, 0.5F));
	return true;
}

int HitPoint::getMaxValue() const {
	return this->maxValue;
}

void HitPoint::setMaxValue(int maxValue) {
	if (this->maxValue < 1) {
		_throw(ArgumentException, "maxValue must >= 1");
	}
	this->value = _min(this->value, this->maxValue = maxValue);
}

int HitPoint::getValue() const {
	return this->value;
}

void HitPoint::setValue(int value) {
	this->value = _min(_max(value, 0), this->maxValue);
}

ccColor4F HitPoint::getFullColor() const {
	return this->fullColor;
}

void HitPoint::setFullColor(ccColor4F fullColor) {
	this->fullColor = fullColor;
}

ccColor4F HitPoint::getHalfColor() const {
	return this->halfColor;
}

void HitPoint::setHalfColor(ccColor4F halfColor) {
	this->halfColor = halfColor;
}

ccColor4F HitPoint::getEmptyColor() const {
	return this->emptyColor;
}

void HitPoint::setEmptyColor(ccColor4F emptyColor) {
	this->emptyColor = emptyColor;
}

ccColor4F HitPoint::getBackgroundColor() const {
	return this->backgroundColor;
}

void HitPoint::setBackgroundColor(ccColor4F backgroundColor) {
	this->backgroundColor = backgroundColor;
}

ccColor4F HitPoint::getBorderColor() const {
	return this->borderColor;
}

void HitPoint::setBorderColor(ccColor4F borderColor) {
	this->borderColor = borderColor;
}

void HitPoint::draw() {
	CC_PROFILER_START_CATEGORY(kCCProfilerCategorySprite, "HitPoint - draw");
	CC_NODE_DRAW_SETUP();
	
	CCSize contentSize = this->getContentSize();
	ccDrawSolidRect(CCPoint(contentSize.width * this->value / this->maxValue, 0), CCPoint(contentSize.width, contentSize.height), this->backgroundColor);

	if (contentSize.width > 0) {
		ccColor4F color;
		int halfValue = this->maxValue / 2;
		if (this->value == halfValue) {
			color = this->halfColor;
		} else {
			bool lessThanHalf = this->value < halfValue;
			ccColor4F &begin = lessThanHalf ? this->emptyColor : this->halfColor;
			ccColor4F &end = lessThanHalf ? this->halfColor : this->fullColor;
			float rate = lessThanHalf ? (float)this->value / halfValue : (float)(this->value - halfValue) / halfValue;
			color.r = _min(1.0F, _max(0.0F, begin.r + (end.r - begin.r) * rate));
			color.g = _min(1.0F, _max(0.0F, begin.g + (end.g - begin.g) * rate));
			color.b = _min(1.0F, _max(0.0F, begin.b + (end.b - begin.b) * rate));
			color.a = _min(1.0F, _max(0.0F, begin.a + (end.a - begin.a) * rate));
		} 
		ccDrawSolidRect(
			CCPoint(0, 0), 
			CCPoint(contentSize.width * this->value / this->maxValue, contentSize.height),
			color);
	}
	
	const ccColor4F &bColor = this->borderColor;
	ccDrawColor4F(bColor.r, bColor.g, bColor.b, bColor.a);
	ccDrawRect(CCPoint(0, 0), CCPoint(contentSize.width, contentSize.height));

	CC_INCREMENT_GL_DRAWS(1);
	CC_PROFILER_STOP_CATEGORY(kCCProfilerCategorySprite, "HitPoint - draw");
}
